/**
 * Copyright 2009 Adam Ruggles.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.code.sapien.security;

import java.io.Serializable;

import javax.persistence.Embeddable;
import javax.persistence.Transient;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

/**
 * A Collection of permissions used to associate a category with a role.
 * @author Adam
 * @version $Id: CategoryPermissions.java 30 2010-01-10 19:05:55Z a.ruggles $
 * 
 * Created on Mar 5, 2009 at 9:05:04 PM 
 */
@Embeddable
public class CategoryPermissions extends AbstractPermissions implements Serializable {
	/**
	 * Add discussion constant value.
	 */
	public static final int ADD_DISCUSSION_VALUE = 1;

	/**
	 * Add response constant value.
	 */
	public static final int ADD_RESPONSE_VALUE = 1 << 2;

	/**
	 * Edit discussion constant value.
	 */
	public static final int EDIT_DISCUSSION_VALUE = 1 << 3;

	/**
	 * Edit response constant value.
	 */
	public static final int EDIT_RESPONSE_VALUE = 1 << 4;

	/**
	 * Remove discussion constant value.
	 */
	public static final int REMOVE_DISCUSSION_VALUE = 1 << 5;

	/**
	 * Remove response constant value.
	 */
	public static final int REMOVE_RESPONSE_VALUE = 1 << 6;

	/**
	 * Can read discussions and responses for this category.
	 */
	public static final int READ_VALUE = 1 << 9;

	/**
	 * Serial Version UID.
	 */
	private static final long serialVersionUID = 505723561016715402L;

	/**
	 * Set lock constant value.
	 */
	public static final int SET_LOCK_VALUE = 1 << 7;

	/**
	 * Set sticky constant value.
	 */
	public static final int SET_STICKY_VALUE = 1 << 8;

	/**
	 * Default constructor.
	 */
	public CategoryPermissions() {
		super();
	}

	/**
	 * Constructs a new CategoryPemissions with the same permissions.
	 * @param permissions A CategoryPermissions to initialize to.
	 */
	public CategoryPermissions(final CategoryPermissions permissions) {
		super(permissions.getValue());
	}

	/**
	 * Constructs a category permissions with a value.
	 * @param value The value to set.
	 */
	public CategoryPermissions(final int value) {
		super(value);
	}

	/**
	 * Constructs a CategoryPermissions with an array of role permission values.
	 * @param permissions An array of category permission values.
	 */
	public CategoryPermissions(final int[] permissions) {
		super();
		for (int permission : permissions) {
			add(permission);
		}
	}

	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(final Object obj) {
		if (this == obj) {
			return true;
		}
		if (!(obj instanceof CategoryPermissions)) {
			return false;
		}
		final CategoryPermissions rhs = (CategoryPermissions) obj;
		return new EqualsBuilder()
			.append(getValue(), rhs.getValue())
			.isEquals();
	}

	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return new HashCodeBuilder(3, 7)
			.append(getValue())
			.toHashCode();
	}

	/**
	 * Returns true if the add discussion permission is set to true.
	 * @return true if the add discussion permission is set to true.
	 */
	public boolean isCanAddDiscussion() {
		return isValueSet(ADD_DISCUSSION_VALUE);
	}

	/**
	 * Returns true if the add response permission is set to true.
	 * @return true if the add response permission is set to true.
	 */
	public boolean isCanAddResponse() {
		return isValueSet(ADD_RESPONSE_VALUE);
	}

	/**
	 * Returns true if the edit discussion permission is set to true.
	 * @return true if the edit discussion permission is set to true.
	 */
	public boolean isCanEditDiscussion() {
		return isValueSet(EDIT_DISCUSSION_VALUE);
	}

	/**
	 * Returns true if the edit response permission is set to true.
	 * @return true if the edit response permission is set to true.
	 */
	public boolean isCanEditResponse() {
		return isValueSet(EDIT_RESPONSE_VALUE);
	}

	/**
	 * Returns true if the read permission is set to true.
	 * @return true if the read permission is set to true.
	 */
	@Transient
	public boolean isCanRead() {
		return isValueSet(READ_VALUE);
	}

	/**
	 * Returns true if the remove discussion permission is set to true.
	 * @return true if the remove discussion permission is set to true.
	 */
	public boolean isCanRemoveDiscussion() {
		return isValueSet(REMOVE_DISCUSSION_VALUE);
	}

	/**
	 * Returns true if the remove response permission is set to true.
	 * @return true if the remove response permission is set to true.
	 */
	public boolean isCanRemoveResponse() {
		return isValueSet(REMOVE_RESPONSE_VALUE);
	}

	/**
	 * Returns true if the set lock permission is set to true.
	 * @return true if the set lock permission is set to true.
	 */
	public boolean isCanSetLock() {
		return isValueSet(SET_LOCK_VALUE);
	}

	/**
	 * Returns true if the set sticky permission is set to true.
	 * @return true if the set sticky permission is set to true.
	 */
	public boolean isCanSetSticky() {
		return isValueSet(SET_STICKY_VALUE);
	}

	/**
	 * Sets canAddDiscussion.
	 * @param canAddDiscussion the canAddDiscussion to set.
	 */
	public void setCanAddDiscussion(final boolean canAddDiscussion) {
		if (canAddDiscussion) {
			add(ADD_DISCUSSION_VALUE);
		} else {
			remove(ADD_DISCUSSION_VALUE);
		}
	}

	/**
	 * Sets canAddResponse.
	 * @param canAddResponse the canAddResponse to set.
	 */
	public void setCanAddResponse(final boolean canAddResponse) {
		if (canAddResponse) {
			add(ADD_RESPONSE_VALUE);
		} else {
			remove(ADD_RESPONSE_VALUE);
		}
	}

	/**
	 * Sets canEditDiscussion.
	 * @param canEditDiscussion the canEditDiscussion to set.
	 */
	public void setCanEditDiscussion(final boolean canEditDiscussion) {
		if (canEditDiscussion) {
			add(EDIT_DISCUSSION_VALUE);
		} else {
			remove(EDIT_DISCUSSION_VALUE);
		}
	}

	/**
	 * Sets canEditResponse.
	 * @param canEditResponse the canEditResponse to set.
	 */
	public void setCanEditResponse(final boolean canEditResponse) {
		if (canEditResponse) {
			add(EDIT_RESPONSE_VALUE);
		} else {
			remove(EDIT_RESPONSE_VALUE);
		}
	}

	/**
	 * Sets canRead.
	 * @param canRead the canRead to set.
	 */
	public void setCanRead(final boolean canRead) {
		if (canRead) {
			add(READ_VALUE);
		} else {
			remove(READ_VALUE);
		}
	}

	/**
	 * Sets canRemoveDiscussion.
	 * @param canRemoveDiscussion the canRemoveDiscussion to set.
	 */
	public void setCanRemoveDiscussion(final boolean canRemoveDiscussion) {
		if (canRemoveDiscussion) {
			add(REMOVE_DISCUSSION_VALUE);
		} else {
			remove(REMOVE_DISCUSSION_VALUE);
		}
	}

	/**
	 * Sets canRemoveResponse.
	 * @param canRemoveResponse the canRemoveResponse to set.
	 */
	public void setCanRemoveResponse(final boolean canRemoveResponse) {
		if (canRemoveResponse) {
			add(REMOVE_RESPONSE_VALUE);
		} else {
			remove(REMOVE_RESPONSE_VALUE);
		}
	}

	/**
	 * Sets canSetLock.
	 * @param canSetLock the canSetLock to set.
	 */
	public void setCanSetLock(final boolean canSetLock) {
		if (canSetLock) {
			add(SET_LOCK_VALUE);
		} else {
			remove(SET_LOCK_VALUE);
		}
	}

	/**
	 * Sets canSetSticky.
	 * @param canSetSticky the canSetSticky to set.
	 */
	public void setCanSetSticky(final boolean canSetSticky) {
		if (canSetSticky) {
			add(SET_STICKY_VALUE);
		} else {
			remove(SET_STICKY_VALUE);
		}
	}

	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return new ToStringBuilder(this)
			.append("canRead", isCanRead())
			.append("canAddDiscussion", isCanAddDiscussion())
			.append("canAddResponse", isCanAddResponse())
			.append("canEditDiscussion", isCanEditDiscussion())
			.append("canEditResponse", isCanEditResponse())
			.append("canRemoveDiscussion", isCanRemoveDiscussion())
			.append("canRemoveResponse", isCanRemoveResponse())
			.append("canSetLock", isCanSetLock())
			.append("canSetSticky", isCanSetSticky())
			.toString();
	}
}
